home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / mg2a_src.zip / SYS / AMIGA / MENUSTAC.C < prev    next >
C/C++ Source or Header  |  1988-08-23  |  11KB  |  344 lines

  1. /*
  2.  *  Simple menu package.  Needs lotsa work to handle some cases.
  3.  *
  4.  *  Copyright 1985
  5.  *  Louis A. Mamakos
  6.  *  Software & Stuff
  7.  *  14813 Ashford Place
  8.  *  Laurel, MD  20707
  9.  *
  10.  *  For non-commerical use only.  This program, or any modifications, may not
  11.  *  be sold or incorporated into any product without prior permission from the
  12.  *  author.
  13.  *
  14.  *  Modified by mwm to handle "stacking" menus.
  15.  *    NB - adding item to a menu that's been "popped" back to doesn't work,
  16.  *    and probably never will.
  17.  *  Modified again by MPK to allow subitems again (non-stacking), and
  18.  *  fix bug when visiting files not in last menu.
  19.  *
  20.  *  Modified once again by MPK to avoid calling strsave() if desired.  This
  21.  *    is controlled by the newly-added last parameter to *_Add(), which
  22.  *    indicates whether the menu name should be saved off by strsave().
  23.  *      I suppose *not* saving strings might break on a system where
  24.  *    MEMF_PUBLIC meant something, but I think that's far in the future...
  25.  */
  26.  
  27. #include <exec/types.h>
  28. #include <exec/nodes.h>
  29. #include <exec/lists.h>
  30. #include <exec/ports.h>
  31. #include <exec/devices.h>
  32. #include <exec/memory.h>
  33. #include <hardware/blit.h>
  34. #include <graphics/copper.h>
  35. #include <graphics/regions.h>
  36. #include <graphics/rastport.h>
  37. #include <graphics/gfxbase.h>
  38. #include <graphics/gels.h>
  39. #include <intuition/intuition.h>
  40.  
  41. #define MNUM(menu,item,sub) (SHIFTMENU(menu)|SHIFTITEM(item)|SHIFTSUB(sub))
  42. #define    Menu_Clear    DisposeMenus    /* For ttyio.c    */
  43.  
  44. extern    char    *AllocMem();
  45. extern    char    *AllocRemember();
  46.  
  47. struct    Mem_Node {
  48.    struct Node mn_Node;
  49.    struct Remember mn_Memory;
  50.    struct Menu *mn_Menu;
  51.    } *Top, *RemHead();
  52.  
  53. extern struct Screen WBInfo;    /* For Screen width & Height    */
  54. #define SCREENHEIGHT    (WBInfo . Height)
  55. #define SCREENWIDTH    (WBInfo . Width)
  56.  
  57. static struct List Memory;
  58. static int Cur_Menu, Cur_MenuItem, Cur_SubItem;
  59. static struct Menu *LastMenu;
  60. static struct MenuItem *LastMenuItem, *LastSubItem;
  61.  
  62. struct Menu *AutoMenu;      /* menu struct being dynamically built */
  63.  
  64. char *strsave();        /* Save a string in the remember list */
  65.  
  66. #ifdef LATTICE
  67. void
  68. #endif
  69. Menu_Init()
  70. {
  71.    Memory.lh_Head = (struct Node *) &(Memory.lh_Tail);
  72.    Memory.lh_TailPred = (struct Node *) &(Memory.lh_Head);
  73.    Memory.lh_Tail = NULL;
  74.    Memory.lh_Type = NT_MEMORY;
  75.    Top = NULL;
  76.    Cur_Menu = Cur_MenuItem = Cur_SubItem = -1;
  77.    AutoMenu = LastMenu = NULL;     /* no menu chain yet */
  78.    LastMenuItem = LastSubItem = NULL;
  79. }
  80.  
  81. #ifdef LATTICE
  82. void
  83. #endif
  84. Menu_Clear()
  85. {
  86.  
  87.    while ((Top = RemHead(&Memory)) != NULL) {
  88.       FreeRemember(&(Top->mn_Memory), (LONG)TRUE);
  89.       FreeMem(Top, (LONG)sizeof(struct Mem_Node));
  90.   }
  91.   Menu_Init();            /* Just for safeties sake */
  92. }
  93.  
  94. #ifdef LATTICE
  95. void
  96. #endif
  97. Menu_Pop()
  98. {
  99.  
  100.    if ((Top = RemHead(&Memory)) == NULL) return;
  101.    FreeRemember(&(Top->mn_Memory), (LONG)TRUE);
  102.    FreeMem(Top, (LONG)sizeof(struct Mem_Node));
  103.    /* Now, set Top back to the real list head */
  104.    Top = (struct Mem_Node *) Memory.lh_Head;
  105.    LastMenu = Top->mn_Menu;
  106.    LastMenu->NextMenu = NULL;    /* Tie off the menu list */
  107.    LastMenuItem = NULL;        /* Wrong, but you can't add items here anyway */
  108.    LastSubItem = NULL;        /*    ditto                      */
  109.    Cur_Menu--;
  110. }
  111.  
  112. /*
  113.  *  Add a MENU item.  Args are the text of the menu item, and an enable
  114.  *  flag.  Returns an Intuition type menu number, with the MenuItem and
  115.  *  Menu SubItem being NOITEM and NOSUB.  The MENUITEM part is valid.
  116.  */
  117. /* dummy Intuitext used to calculate length of menu names */
  118. static struct IntuiText itd = {
  119.    AUTOFRONTPEN, AUTOBACKPEN, JAM2, 1, 1, NULL, NULL, NULL
  120. };
  121.  
  122. Menu_Add(name, enabled, saveit)
  123.    char *name;
  124.    int enabled;
  125.    int saveit;
  126. {
  127.    register struct Menu *m;
  128.  
  129.    if ((Top = (struct Mem_Node *) AllocMem(
  130.          (LONG)sizeof(struct Mem_Node), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  131.       return NULL;
  132.    Top->mn_Node.ln_Type = NT_MEMORY;
  133.  
  134.    if ((m = (struct Menu *)AllocRemember(&(Top->mn_Memory),
  135.                  (LONG)sizeof (struct Menu), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  136.       return NULL;
  137.    Top->mn_Menu = m;
  138.  
  139.    if (LastMenu == NULL)
  140.       AutoMenu = m;     /* first menu on list */
  141.    else
  142.       LastMenu->NextMenu = m;      /* link it in */
  143.  
  144.    LastMenuItem = NULL;            /* end of previous MenuItem list */
  145.    LastSubItem = NULL;
  146.    Cur_MenuItem = Cur_SubItem = -1; /* reset item numbers */
  147.    if (LastMenu == NULL)
  148.       m->LeftEdge = 0;
  149.    else
  150.       m->LeftEdge = LastMenu->LeftEdge + LastMenu->Width;
  151.    m->TopEdge = 0;
  152.    itd.IText = (UBYTE *)name;
  153.    m->Width = IntuiTextLength(&itd);
  154.    Top->mn_Node.ln_Name = m->MenuName = saveit ? strsave(name) : name;
  155.    m->Height = 0;
  156.    m->Flags = enabled ? MENUENABLED : 0;
  157.    m->FirstItem = NULL;
  158.    LastMenu = m;
  159.  
  160.    AddHead(&Memory, Top);
  161.    return MNUM(++Cur_Menu, NOITEM, NOSUB);
  162. }
  163.  
  164. /*
  165.  *  Add a menu item to the current MENU.  Note that Add_Menu *must* be
  166.  *  called before this function.
  167.  */
  168. Menu_Item_Add(name, flags, mux, ch, saveit)
  169.    char *name;        /* name of menu item */
  170.    USHORT flags;
  171.    LONG mux;        /* mutual exclusion mask */
  172.    BYTE ch;        /* command sequence character, if COMMSEQ */
  173.    int saveit;        /* save name using strsave? */
  174. {
  175.    register struct MenuItem *m, *n;
  176.    register struct IntuiText *it;
  177.  
  178.    flags &= CHECKIT|CHECKED|COMMSEQ|MENUTOGGLE|ITEMENABLED|HIGHCOMP|HIGHBOX;
  179.    if (LastMenu == NULL)
  180.       return MNUM(NOMENU, NOITEM, NOSUB);
  181.  
  182.    if ((m = (struct MenuItem *) AllocRemember(&(Top->mn_Memory),
  183.            (LONG)sizeof(struct MenuItem), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  184.       return MNUM(NOMENU, NOITEM, NOSUB);
  185.  
  186.    LastSubItem = NULL;        /* terminate possible list of subitems */
  187.    Cur_SubItem = -1;
  188.    if (LastMenuItem == NULL)
  189.       LastMenu->FirstItem  = m;
  190.    else
  191.       LastMenuItem->NextItem = m;
  192.    m->Flags = flags | ITEMTEXT;
  193.    /*
  194.     *  Check for highlight mode:  if none selected, use HIGHCOMP
  195.     */
  196.    if ((m->Flags & (HIGHCOMP | HIGHBOX)) == 0)
  197.       m->Flags |= HIGHCOMP;
  198.    m->Command = ch;
  199.    m->MutualExclude = mux;
  200.    m->SubItem = NULL;
  201.    m->ItemFill = (APTR) AllocRemember(&(Top->mn_Memory),
  202.                  (LONG)sizeof(struct IntuiText), MEMF_PUBLIC | MEMF_CLEAR);
  203.    it = (struct IntuiText *) m->ItemFill;
  204.    it->FrontPen = AUTOFRONTPEN;
  205.    it->BackPen = AUTOBACKPEN;
  206.    it->DrawMode = JAM2;
  207.    if (flags & CHECKIT)
  208.       it->LeftEdge = CHECKWIDTH + 1;
  209.    else
  210.       it->LeftEdge = 1;
  211.    it->TopEdge = 1;
  212.    it->ITextFont = NULL;      /* default font */
  213.    it->IText = (UBYTE *)(saveit ? strsave(name) : name);
  214.    it->NextText = NULL;
  215.    if (LastMenuItem == NULL) {
  216.       m->TopEdge = 2;
  217.       m->LeftEdge = 0;
  218.    } else if (LastMenuItem->TopEdge + 40 > SCREENHEIGHT) {
  219.       m->TopEdge = 2;
  220.       m->LeftEdge = LastMenuItem->LeftEdge + LastMenuItem->Width + 12;
  221.       if (m->LeftEdge > SCREENWIDTH) {
  222.       LastMenuItem->NextItem = NULL;
  223.       LastMenuItem->Flags &= ~ITEMENABLED;
  224.             return MNUM(NOMENU, NOITEM, NOSUB);
  225.       }
  226.    } else {
  227.       m->TopEdge = LastMenuItem->TopEdge + 10;
  228.       m->LeftEdge = LastMenuItem->LeftEdge;
  229.    }
  230.    m->Width = 0;
  231.    if (flags & CHECKIT)
  232.       m->Width += CHECKWIDTH;
  233.    if (flags & COMMSEQ)
  234.       m->Width += COMMWIDTH + 20;
  235.    m->Width += IntuiTextLength(m->ItemFill);
  236.    m->Height = 10;
  237.    /*
  238.     *  Check last menu item's width to see if it is larger than this
  239.     *  item's.  If new item is larger, then update width of all other
  240.     *  items.
  241.     */
  242.    if (LastMenuItem) {
  243.       if (LastMenuItem->Width > m->Width)
  244.         m->Width = LastMenuItem->Width;
  245.       else {
  246.          register short delta = m->Width - LastMenuItem->Width;
  247.  
  248.      for (n = LastMenu->FirstItem; n != m; n = n->NextItem) {
  249.         n->Width = m->Width;
  250.         if (n->LeftEdge > 0) n->LeftEdge += delta;
  251.      }
  252.      if (m->LeftEdge > 0) m->LeftEdge += delta;
  253.       }
  254.    }
  255.    LastMenuItem = m;
  256.    return MNUM(Cur_Menu, ++Cur_MenuItem, NOSUB);
  257. }
  258.  
  259.  
  260.  
  261. Menu_SubItem_Add(name, flags, mux, ch, saveit)
  262.    char *name, ch;
  263.    USHORT flags;
  264.    LONG mux;
  265.    int saveit;
  266. {
  267.    register struct M